// user
package implement

import (
	"log"
	"net/http"
	"path/filepath"
	"strings"

	"encoding/xml"

	"io"

	"fmt"
	"io/ioutil"

	"net/url"

	"awfan.cn/utils"
	"github.com/gorilla/websocket"
	"gopkg.in/mgo.v2"
)

type SMTP_XML struct {
	XMLName    xml.Name `xml:"smtp"`
	ServerName string   `xml:"serverName"`
	ServerIP   string   `xml:"serverIP"`
}

func Keep(w http.ResponseWriter, r *http.Request) {
	c, err := Upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	log.Println("#ip connected: ", c.RemoteAddr())

	_, token, err := c.ReadMessage()
	if err != nil {
		log.Println("read:", err)
		return
	}

	log.Println("#token:", string(token))

	Clients[string(token)] = c

	for {
		data := utils.WEBSOCKET_DATA{}

		err = c.ReadJSON(&data)

		if err != nil {
			log.Println("read json:", err.Error())
			break
		}

		go dowork(data.Action, data.Data, c)
	}

	delete(Clients, string(token))
	log.Println("#finished connection")
}

func dowork(action string, data interface{}, c *websocket.Conn) {
	wsHandle, exist := WSC[action]

	if !exist {
		utils.WriteWsError(action, 404, "#action not supported", c)
	} else {
		session, err := mgo.Dial("127.0.0.1")

		if err != nil {
			utils.WriteWsError(action, 404, err.Error(), c)
		} else {
			defer session.Close()

			db := session.DB(utils.MONGO_DATABASE)

			wsHandle(action, data, c, db)
		}
	}
}

func Union(w http.ResponseWriter, r *http.Request) {
	path := strings.Replace(r.URL.Path, utils.API_ROUTES, "", 1)

	var h2 func(*url.URL, http.ResponseWriter, []byte, *mgo.Database)
	var h1 func(*url.URL, http.ResponseWriter, *mgo.Database)

	var exist bool

	switch r.Method {

	case "POST":
		h2, exist = POST[path]
	case "DELETE":
		h1, exist = DEL[path]
	case "PUT":
		h2, exist = PUT[path]
	case "GET":
		h1, exist = GET[path]
	default:
		utils.WriteError(filepath.Ext(r.URL.Path), 501, fmt.Sprintf("#not supported method: %v", r.Method), w)
		return
	}

	if !exist {
		utils.WriteError(filepath.Ext(r.URL.Path), 500, fmt.Sprintf("#api '%v' not implement", path), w)
		return
	}

	session, err := mgo.Dial("127.0.0.1")

	if err != nil {
		utils.WriteError(filepath.Ext(r.URL.Path), 500, err.Error(), w)
		return
	}

	defer session.Close()

	db := session.DB(utils.MONGO_DATABASE)

	if h1 != nil {
		h1(r.URL, w, db)
	} else {
		b, err := ioutil.ReadAll(r.Body)

		if err != nil {
			utils.WriteError(filepath.Ext(r.URL.Path), 500, err.Error(), w)
			return
		}

		h2(r.URL, w, b, db)
	}

}

func append(path string, method string, handler func(*url.URL, http.ResponseWriter, []byte, *mgo.Database)) {
	switch method {

	case "PUT":
		PUT[path+".xml"] = handler
		PUT[path+".json"] = handler
		PUT[path+".html"] = handler
	case "POST":
		POST[path+".xml"] = handler
		POST[path+".json"] = handler
		POST[path+".html"] = handler

	default:
		log.Println("#NOT SUPPORTED METHOD:", method)
	}
}

func append2(path string, method string, handler func(*url.URL, http.ResponseWriter, *mgo.Database)) {
	switch method {
	case "GET":
		GET[path+".xml"] = handler
		GET[path+".json"] = handler
		GET[path+".html"] = handler
	case "DELETE":
		DEL[path+".xml"] = handler
		DEL[path+".json"] = handler
		DEL[path+".html"] = handler
	default:
		log.Println("#NOT SUPPORTED METHOD:", method)
	}
}

func FuncRoot(w http.ResponseWriter, r *http.Request) {

	io.WriteString(w, "Hello world!")
}
